package com.liuyk.util;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.liuyk.Constants;
import com.liuyk.entity.Channel;
import com.liuyk.entity.DefaultOrderMenuItems;
import com.liuyk.entity.Subscriptions;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * Json工具
 * <p>
 * Created by Administrator on 2015/9/10.
 */
public class JsonUtil {

    public static String getJsonText(InputStream in) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            int len;
            byte[] buff = new byte[1024];
            while ((len = in.read(buff)) != -1) {
                out.write(buff, 0, len);
                out.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toString();
    }

    public static void parseJson(String json) {
        try {
            final JSONObject jsonObject = new JSONObject(json);

            final JSONObject subscriptionsObject = jsonObject.getJSONObject("subscriptions");
            final JSONArray jsonArray = subscriptionsObject.
                    getJSONArray("defaultOrderMenuItems");
            for (int i = 0; i < jsonArray.length(); i++) {
                final DefaultOrderMenuItems adm = new DefaultOrderMenuItems();
                adm.setValue(jsonArray.getString(i));
                Subscriptions.defaultOrderMenuItems.add(adm);
//                Constants.defaultOrderMenuItems.add(jsonArray.getString(i));
            }

            final JSONObject channelsObject = subscriptionsObject.getJSONObject("channels");
            final Iterator<String> iterator = channelsObject.keys();
            while (iterator.hasNext()) {
                final JSONObject jo = channelsObject.getJSONObject(iterator.next());
                final Channel channel = new Channel();
                channel.setChannelName(jo.getString("channelName"));
                channel.setChannelUrl(jo.getString("channelUrl"));
                Subscriptions.channels.add(channel);
//                Constants.channels.add(channel);
            }

            Constants.version = jsonObject.getString(Constants.version);
            Constants.device_info = jsonObject.getString(Constants.device_info);
            Constants.adv_distance_url = jsonObject.getString(Constants.adv_distance_url);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void parseJson_1(String json, Object constants) {
        try {
            final JSONObject jsonObject = new JSONObject(json);

            final Class<?> constantsClass = constants.getClass();
            final Field[] fields = constantsClass.getDeclaredFields();
            for (Field field : fields) {
                //对私有字段访问,取消权限检查,强制访问
                field.setAccessible(true);
                String name = field.getName();
                if (name.contains("CONFIG_NAME") || name.contains("CHANNEL_FILE_NAME")) {
                    continue;
                }

                if (field.getGenericType().toString().equals("class java.lang.String")) {
                    String result = jsonObject.getString(name);
                    field.set(constants, result);
//                    Log.i("result", "result: " + result);
                } else {
                    Log.i("result", "result: " + name);
                    jsonCollection(constantsClass, constants, jsonObject, name);
                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void jsonCollection(Class<?> constantsClass, Object constants, JSONObject jsonObject, String name) {
        try {
            final Method[] declaredMethods = constantsClass.getDeclaredMethods();
            for (Method method : declaredMethods) {
                if (method.getName().contains("getBean")) {
                    final ArrayList list = (ArrayList) method.invoke(constants, name);
                    final Class<?> c = list.get(0).getClass();//Channel
                    list.clear();//清楚无用的数据

                    //获取json确定的类型
                    final Object jsonFieldType = c.getDeclaredField("json").get("json");
                    if (jsonFieldType.equals("jsonObject")) {

                        final JSONObject jo = jsonObject.getJSONObject(name);
                        jsonObject(list, jo, c);

                    } else if (jsonFieldType.equals("jsonArray")) {

                        final JSONArray js = jsonObject.getJSONArray(name);
                        jsonArray(list, js, c);

                    } else if (jsonFieldType.equals("jsonObjectArray")) {

                        list.add(c.newInstance());
                        final JSONObject jo = jsonObject.getJSONObject(name);
                        for (Field f : c.getDeclaredFields()) {
                            if (f.getName().contains("serialVersionUID") ||
                                    f.getName().equals("json")) {
                                continue;
                            }
                            jsonCollection(c, c.newInstance(), jo, f.getName());
                        }

                    }
                    break;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void jsonObject(ArrayList invoke, JSONObject jsonObject, Class<?> clazz) {
        try {
            final Iterator<String> iterator = jsonObject.keys();
            while (iterator.hasNext()) {
                final JSONObject jo = jsonObject.getJSONObject(iterator.next());
                final Object o = clazz.newInstance();
                final Field[] f1 = clazz.getDeclaredFields();
                for (Field f : f1) {
                    f.setAccessible(true);
                    String channelName = f.getName();
                    if (channelName.contains("serialVersionUID") ||
                            channelName.equals("json")) {
                        continue;
                    }
                    f.set(o, jo.getString(channelName));
                }
                invoke.add(o);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void jsonArray(ArrayList invoke, JSONArray jsonArray, Class<?> clazz) {
        try {
            for (int i = 0; i < jsonArray.length(); i++) {
                final Object o = clazz.newInstance();
                final Field[] f1 = clazz.getDeclaredFields();
                for (Field f : f1) {
                    f.setAccessible(true);
                    String channelName = f.getName();
                    if (channelName.contains("serialVersionUID") || channelName.equals("json")) {
                        continue;
                    }
                    Log.i("result", "result: " + jsonArray.getString(i));
                    f.set(o, jsonArray.getString(i));
                }
                invoke.add(o);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析本地文件json格式数据
     *
     * @param context
     * @param clazz
     * @param name    assets文件夹中json文件名
     * @param <T>
     * @return
     */
    public static <T> T parseJson(Context context, Class<T> clazz, String name) {
        try {
            InputStream in = context.getResources().getAssets().open(name);
            return parseJson(clazz, getString(in));
        } catch (IOException e) {
            return null;
        }
    }

    public static <T> List<T> parseJson(Context context, String fileName, Class<T[]> clazz) {
        try {
            final InputStream in = context.getResources().getAssets().open(fileName);
            final String jsonText = new String(getString(in));
            final Gson gson = new Gson();
            List<T> list;

            if (!TextUtils.isEmpty(jsonText)) {
                final T[] t = gson.fromJson(jsonText, clazz);
                list = Arrays.asList(t);
                return list;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] getString(InputStream in) {
        ByteArrayOutputStream byo = new ByteArrayOutputStream();
        try {
            byte[] buff = new byte[1024];
            int len;
            while ((len = in.read(buff)) != -1) {
                byo.write(buff, 0, len);
                byo.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null)
                try {
                    in.close();
                    byo.close();
                } catch (IOException ie) {
                    Log.i("value", "IOException" + ie.toString());
                }
        }
        return byo.toByteArray();
    }

    /**
     * 解析json
     *
     * @param type
     * @param data
     * @param <T>
     * @return
     */
    public static <T> T parseJson(Class<T> type, byte[] data) {
        final Gson gson = new Gson();
        T result;
        try {
            result = gson.fromJson(new String(data), type);
        } catch (Exception e) {
            result = null;
        }
        return result;
    }

    public static <T> String toJson(List<T> clazz) {
        try {
            final Gson gson = new Gson();
            return gson.toJson(clazz);
        } catch (Exception e) {
            return null;
        }
    }
}
